package com.appleyk.controller;

import com.appleyk.config.ThreadPoolConfig;
import com.appleyk.plan.PlanPerformService;
import com.appleyk.task.DataCleanTask;
import com.appleyk.task.InfiniteLoopTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * <p>越努力，越幸运</p>
 * 线程池执行任务接口测试
 * @author appleyk
 * @version V.0.1.1
 * @blob https://blog.csdn.net/appleyk
 * @date created on  9:04 下午 2020/12/23
 */
@CrossOrigin
@RestController
@RequestMapping("/task")
public class TaskController {

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    @Autowired
    private ScheduledThreadPoolExecutor delayTaskExecutor;

    @Autowired
    private PlanPerformService planPerformService;

    @Resource
    private ThreadPoolConfig poolConfig;


    @GetMapping("/loop/test")
    public String taskOutPut() {
        // 这里，为了充分地了解线程池的工作负荷情况，特在执行任务时对线程池进行监控
        // 当前线程池中活动的线程（就是正在处理任务的线程有多少个）
        int activeCount = taskExecutor.getActiveCount();
        // 当前池子里存在的线程数量（包括核心的和非核心的）
        int poolSize = taskExecutor.getPoolSize();
        // 当前任务队列中等待任务的数量
        int queueSize = taskExecutor.getThreadPoolExecutor().getQueue().size();
        System.out.println("================ 线程池负荷情况 =================");

        if(activeCount == poolConfig.getMaximumPoolSize()){
            System.out.println("线程池已经满负荷了，无法再继续执行任务了");
            return "对不起，拒绝再接收任务！";
        }
        if(poolSize == taskExecutor.getCorePoolSize()){
            System.out.println("核心线程已用完，任务将移交到队列里...");
        }
        if(queueSize == poolConfig.getQueueCapacity()){
            System.out.println("任务队列已满，准备创建非核心线程...");
        }

        taskExecutor.execute(new InfiniteLoopTask());
        System.out.println("poolSize："+taskExecutor.getPoolSize());
        System.out.println("activeCount："+taskExecutor.getActiveCount());
        System.out.println("queueSize："+taskExecutor.getThreadPoolExecutor().getQueue().size());
        return "恭喜你，任务被成功接纳！";
    }

    /**
     * 延迟多少秒（2s）后，执行一次任务
     * @return
     */
    @GetMapping("/delay/test")
    public String taskDelayed() {
        delayTaskExecutor.schedule(new DataCleanTask(), 2000, TimeUnit.MILLISECONDS);
        System.out.println("========== 定时任务已开启，等待执行==========");
        return "定时任务已开启，稍后看成效！";
    }

    /**
     * 延迟多少秒（2s）后，每隔一段时间（3s）执行一次任务（周期性执行）
     * @return
     */
    @GetMapping("/fixed/delay/test")
    public String taskFixedDelay() {
        // 以上一个任务【结束的时间】为开始，经过delay时长后，立即执行任务
        delayTaskExecutor.scheduleWithFixedDelay(new DataCleanTask(), 2,3, TimeUnit.SECONDS);
        System.out.println("========== 定时任务已开启，等待周期性执行==========");
        return "定时任务已开启，稍后看成效！";
    }

    /**
     * 延迟多少秒（2s）后，每隔一段时间（3s）执行一次任务（周期性执行）
     * @return
     */
    @GetMapping("/fixed/rate/test")
    public String taskFixedRate() {
        // 以上一个任务【开始的时间】为开始，如果在period时长到了，上一个任务执行完毕则立即执行任务，否则等待上一个任务执行完毕后在执行
        delayTaskExecutor.scheduleAtFixedRate(new DataCleanTask(), 2,3, TimeUnit.SECONDS);
        System.out.println("========== 定时任务已开启，等待周期性执行==========");
        return "定时任务已开启，稍后看成效！";
    }

    /**
     * 利用cron表达式，周期性执行任务
     * @return
     */
    @GetMapping("/registrar/cron/test")
    public String taskRegistrarByCron() {
        // 从左至右： 秒 分 时 日 月 星期 年（可选）
        // 下面意思是，周一到周五任意分钟任意小时，只要秒数到了5就执行任务
        String triggerValue = "5 * * * * MON-FRI";
        planPerformService.executeByCron(new DataCleanTask(),triggerValue);
        System.out.println("========== 定时任务已开启，等待周期性执行==========");
        return "定时任务已开启，稍后看成效！";
    }

    /**
     * 从上一个任务执行开始算起，一旦到了规定的interval，如果上一个任务执行完毕，则立即执行任务，否则等
     * @return
     */
    @GetMapping("/registrar/fixed/test")
    public String taskRegistrarByFixed() {
        planPerformService.executeByFixedRate(new DataCleanTask(),2);
        System.out.println("========== 定时任务已开启，等待周期性执行==========");
        return "定时任务已开启，稍后看成效！";
    }
}
